
#include "disp.h"
#include "stdio.h"
#include "f1c100s_gpio.h"
#include "f1c100s_intc.h"
#include "f1c100s_pwm.h"
#include "f1c100s_clock.h"
#include "f1c100s_de.h"

uint32_t lcd_gram[LCD_WIDTH * LCD_HIGHT];

de_lcd_config_t lcd_config_43_480x272 = {
    .width = 480,
    .height = 272,
    .bus_width = DE_LCD_R_6BITS | DE_LCD_G_6BITS | DE_LCD_B_6BITS,
    .bus_mode = DE_LCD_PARALLEL_RGB,
    .pixel_clock_hz = 9000000,

    .h_back_porch = 43,
    .h_front_porch = 8,
    .h_sync_len = 4,
    .h_sync_invert = 1,

    .v_back_porch = 12,
    .v_front_porch = 8,
    .v_sync_len = 4,
    .v_sync_invert = 1,
};

de_lcd_config_t lcd_config_43_800x480 = {
    .width = 800,
    .height = 480,
    .bus_width = DE_LCD_R_6BITS | DE_LCD_G_6BITS | DE_LCD_B_6BITS,
    .bus_mode = DE_LCD_PARALLEL_RGB,
    .pixel_clock_hz = 26000000,

    .h_back_porch = 6,
    .h_front_porch = 6,
    .h_sync_len = 3,
    .h_sync_invert = 1,

    .v_back_porch = 10,
    .v_front_porch = 10,
    .v_sync_len = 3,
    .v_sync_invert = 1,
};
de_lcd_config_t *lcd_config;

// LCPI F1C200S开发板 PE6 需要焊接R44-0R
void backlight_init()
{
    gpio_pin_init(GPIOE, 6, GPIO_MODE_AF3, GPIO_PULL_NONE, GPIO_DRV_3);
    pwm_init(PWM1, PWM_MODE_CONTINUOUS, 1, PWM_PSC_120); // 24M / 120 = 200kHz
    pwm_set_period(PWM1, 200);                           // 200k / 200 = 1kHz
    pwm_set_pulse_len(PWM1, 100);
    pwm_enable(PWM1);
}

void disp_de_init()
{
    // 4.3寸 800x480 屏幕资料 https://www.eya-display.com/jlt4305a

    lcd_config = &lcd_config_43_480x272;
    de_lcd_init(lcd_config);
}

void disp_layer_init(uint8_t layer)
{
    debe_layer_init(layer);
    debe_layer_set_size(layer, lcd_config->width, lcd_config->height);
    debe_layer_set_addr(layer, lcd_gram);
    debe_layer_enable(layer);
    debe_layer_set_mode(layer, DEBE_MODE_32BPP_ARGB_8888);
}
void disp_rgb_init()
{
    disp_gpio_init();
    backlight_init();
    disp_de_init();
    debe_set_bg_color(0XFFFFFFFF);
    debe_load(DEBE_UPDATE_AUTO);
    uint8_t layer = 0;
    disp_layer_init(layer);
    disp_fill(0, 50, 200, 80, 0xff00ff00);
}

void disp_gpio_init()
{
    /*******
     *     PD0-PD21 LCD pins
     *     PD0 ->I2C0 SDA (LCD D2)
     *     PD12->I2C0 SCK (LCD D18)
     ******/

    // PD1-PD11
    for (uint8_t i = 1; i <= 11; i++)
    {
        gpio_pin_init(GPIOD, i, GPIO_MODE_AF2, GPIO_PULL_NONE, GPIO_DRV_3);
    }
    // PD13-PD21
    for (uint8_t i = 13; i <= 21; i++)
    {
        gpio_pin_init(GPIOD, i, GPIO_MODE_AF2, GPIO_PULL_NONE, GPIO_DRV_3);
    }
}

void disp_fill(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t color)
{
    uint32_t offset = 0;
    if ((x + w > LCD_WIDTH) || (y + h > LCD_HIGHT))
        return;

    for (uint16_t ypos = y; ypos < (y + h); ypos++)
    {
        offset = (uint32_t)ypos * LCD_WIDTH;
        for (uint16_t xpos = x; xpos < (x + w); xpos++)
        {
            lcd_gram[offset + xpos] = color;
        }
    }
}

inline void disp_pixel(uint16_t x, uint16_t y, uint32_t color)
{
    lcd_gram[x + y * LCD_WIDTH] = color;
}

void disp_clear(uint32_t color)
{
    for(int y=0;y<LCD_HIGHT;y++)
    {
        for(int x=0;x<LCD_WIDTH;x++)
        {
            lcd_gram[x+y*LCD_WIDTH]=color;
        }
    }
}